#include "stdafx.h"
#include "rot.h"
#include "msg.h"

CRotImpl::CRotImpl()
{
}

CRotImpl::~CRotImpl()
{
    logi("CRotImpl::~CRotImpl");
}

HRESULT CRotImpl::CreateInstance(REFCLSID clsid, IBase* punk, REFIID iid, void** ppv)
{
    HRESULT hr = S_OK;
    hr = IsRunning(CLSID_CLoader);
    rc_error(hr == S_OK, E_FAIL);

    SYNC_OBJ(&m_lock)
    RotItem& Item = m_map[CLSID_CLoader];

    CreatorPtr pICreator;
    pICreator.dispose();

    hr = Item.m_ptr->QueryInterface(IID_ICreator, (void**)&pICreator);
    rc_error(hr == S_OK, E_FAIL);

    hr = pICreator->CreateInstance(clsid, punk, iid, ppv);
    rc_error(hr == S_OK, E_FAIL);

    return S_OK;
}
HRESULT CRotImpl::Register(REFCLSID clsid, LPCSTR progid, IBase* punk, ULONG id)
{
    rc_error(S_OK != IsRunning(clsid), E_FAIL);
    SYNC_OBJ(&m_lock)
    RotItem& Item = m_map[clsid];
    Item.progid = progid;
    Item.cls = clsid;
    Item.index = id;
    return punk->QueryInterface(IID_IBase, (void**)&Item.m_ptr);
}

HRESULT CRotImpl::Revoke(REFCLSID clsid)
{
    rc_error(S_OK == IsRunning(clsid), E_INVALIDARG);
    SYNC_OBJ(&m_lock)
    m_map.erase(clsid);
    return S_OK;
}

HRESULT CRotImpl::IsRunning(REFCLSID clsid)
{
    SYNC_OBJ(&m_lock)
    return m_map.end() != m_map.find(clsid) ? S_OK : S_FALSE;
}

HRESULT CRotImpl::GetObject(REFCLSID clsid, REFIID iid, IBase** ppunk)
{
    SYNC_OBJ(&m_lock)
    return GetBaseObject(clsid, iid, ppunk);
}

HRESULT CRotImpl::RevokeAll()
{
    SYNC_OBJ(&m_lock)
    m_map.clear();
    return S_OK;
}

LPCSTR CRotImpl::ProgIDFromCLSID(REFCLSID clsid)
{
    SYNC_OBJ(&m_lock)
    OBJMAP::iterator it = m_map.find(clsid);
    rc_error(!(it != m_map.end()), it->second.progid.c_str());

    CreatorPtr pICreator;
    rc_error(S_SUCCEEDED(GetBaseObject(CLSID_CLoader, IID_ICreator, (IBase**)&pICreator)), "");
    rc_error(pICreator != NULL, "");
    return pICreator->ProgIDFromCLSID(clsid);
}

CLSID CRotImpl::CLSIDFromProgID(LPCSTR progid)
{
    SYNC_OBJ(&m_lock)
    CreatorPtr pICreator;
    rc_error(S_SUCCEEDED(GetBaseObject(CLSID_CLoader, IID_ICreator, (IBase**)&pICreator)), IID_INULL);
    rc_error(pICreator != NULL, IID_INULL);
    return pICreator->CLSIDFromProgID(progid);
}

ULONG CRotImpl::GetObjectCount()
{
    SYNC_OBJ(&m_lock)
    return m_map.size();
}

HRESULT CRotImpl::GetBaseObject(REFCLSID clsid, REFIID iid, IBase** ppunk)
{
    OBJMAP::iterator it = m_map.find(clsid);
    rc_error((m_map.end() != it), E_INVALIDARG);
    rc_error(it->second.m_ptr != NULL, E_INVALIDARG);
    return it->second.m_ptr->QueryInterface(iid, (void**)ppunk);
}
